/*
*         Copyright (c), NXP Semiconductors Bangalore / India
*
*                     (C)NXP Semiconductors
*       All rights are reserved. Reproduction in whole or in part is
*      prohibited without the written consent of the copyright owner.
*  NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
*                          arising from its use.
*/

/** \file
* Generic phDriver Component of Reader Library Framework.
* $Author$
* $Revision$
* $Date$
*
* History:
*  RS: Generated 24. Jan 2017
*
*/


#include "phDriver.h"

#include <DAL/cfg/BoardSelection.h>

#include <BSP.h>
#include <IO.h>

static pphDriver_TimerCallBck_t pTimerIsrCallBack;
static volatile uint32_t dwTimerExp;

static void phDriver_TimerIsrCallBack(void);

phStatus_t phDriver_TimerStart(phDriver_Timer_Unit_t eTimerUnit, uint32_t dwTimePeriod, pphDriver_TimerCallBck_t pTimerCallBack)
{
	uint32_t uclk;
	uint32_t period;
	timer_parameter_struct timer_initpara;
	
	rcu_periph_clock_enable(RCU_TIMER2);
	timer_deinit(TIMER2);
	uclk = rcu_clock_freq_get(CK_APB1)*2;

	period = dwTimePeriod * (PH_DRIVER_TIMER_MICRO_SECS / eTimerUnit);
	if(period > 0xFFFF ){
        return PH_DRIVER_ERROR | PH_COMP_DRIVER;
	}
    if(pTimerCallBack == NULL)
    {    /* Timer Start is blocking call. */
        dwTimerExp = 0;
        pTimerIsrCallBack = phDriver_TimerIsrCallBack;
    }
    else
    {   /* Call the Timer callback. */
        pTimerIsrCallBack = pTimerCallBack;
    }
	
	/* TIMER2 configuration */
	timer_initpara.prescaler         = uclk/1000000U - 1;
	timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
	timer_initpara.counterdirection  = TIMER_COUNTER_UP;
	timer_initpara.period            = period;
	timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
	timer_init(TIMER2, &timer_initpara);
	
	timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
	timer_interrupt_enable(TIMER2, TIMER_INT_UP);
		
	nvic_irq_enable(TIMER2_IRQn, 1, 0);

	timer_enable(TIMER2);
	
    if(pTimerCallBack == NULL)
    {
        /* Block until timer expires. */
        while(!dwTimerExp){
//				taskYIELD();
		}
    }
	
    return PH_DRIVER_SUCCESS;
}

phStatus_t phDriver_TimerStop(void)
{
	timer_disable(TIMER2);
    /* Disable timer interrupt */
	nvic_irq_disable(TIMER2_IRQn);
    return PH_DRIVER_SUCCESS;
}

static phStatus_t phDriver_PinConfigInterrupt(uint8_t bPortNum, uint8_t bPinNum, phDriver_Pin_Config_t *pPinConfig)
{
	return PH_DRIVER_ERROR | PH_COMP_DRIVER;
}

static void IO_Setup(IO_T* io, uint8_t port, uint8_t pin){
	static const uint32_t portTable[] = {
		GPIOA, GPIOB, GPIOC
	};
		
	io->port = (void*)portTable[port];
	io->pin = pin;
}

static phStatus_t phDriver_PinConfigGpio(uint8_t bPortNum, uint8_t bPinNum, phDriver_Pin_Func_t ePinFunc,
        phDriver_Pin_Config_t *pPinConfig)
{
    phStatus_t wStatus = PH_DRIVER_SUCCESS;
	IO_T io;
	
	IO_Setup(&io, bPortNum, bPinNum);
	
    switch(ePinFunc)
    {
    case PH_DRIVER_PINFUNC_INPUT:
		IO_Init(&io, IO_Mode_IN);
        break;

    case PH_DRIVER_PINFUNC_OUTPUT:
		IO_Init(&io, IO_Mode_OUT);
		IO_Set(&io, pPinConfig->bOutputLogic);
        break;

    default:
        wStatus = PH_DRIVER_ERROR | PH_COMP_DRIVER;
    }

    return wStatus;

}


void phDriver_PinReset_Set(uint8_t bValue){
	RFIO_SetReset(bValue);
}

void phDriver_PinNSS_Set(uint8_t bValue){
	RFIO_SPI_SetNSS(bValue);
}


void phDriver_PinClearIntStatus(uint32_t dwPinNumber)
{
}

void TIMER2_IRQHandler(void)
{
	timer_interrupt_flag_clear(TIMER2, TIMER_INT_UP);
	phDriver_TimerStop();
    pTimerIsrCallBack();
}

static void phDriver_TimerIsrCallBack(void)
{
    dwTimerExp = 1;
}

